package com.meilingcloud.research.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilingcloud.biobank.domain.SampleBackup;
import com.meilingcloud.biobank.service.ISampleBackupService;
import com.meilingcloud.common.enums.AttachModule;
import com.meilingcloud.common.utils.SecurityUtils;
import com.meilingcloud.research.domain.RwsTask;
import com.meilingcloud.research.domain.RwsTaskSample;
import com.meilingcloud.research.mapper.RwsTaskMapper;
import com.meilingcloud.research.service.IRwsTaskSampleService;
import com.meilingcloud.research.service.IRwsTaskService;
import com.meilingcloud.system.domain.SysAttach;
import com.meilingcloud.system.service.ISysAttachService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 课题任务 Service业务层处理
 *
 * @author chenl
 * @date 2021-03-23
 */
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Service
public class RwsTaskServiceImpl extends ServiceImpl<RwsTaskMapper, RwsTask> implements IRwsTaskService {

    private final ISysAttachService sysAttachService;
    private final IRwsTaskSampleService rwsTaskSampleService;
    private final ISampleBackupService sampleBackupService;

    @Override
    public List<RwsTask> queryList(RwsTask rwsTask) {
        LambdaQueryWrapper<RwsTask> lqw = Wrappers.lambdaQuery();
        if (rwsTask.getTopicId() != null) {
            lqw.eq(RwsTask::getTopicId, rwsTask.getTopicId());
        }
        if (StringUtils.isNotBlank(rwsTask.getTaskName())) {
            lqw.like(RwsTask::getTaskName, rwsTask.getTaskName());
        }
        lqw.orderByDesc(RwsTask::getCreateTime);
        List<RwsTask> taskList = this.list(lqw);
        if (CollectionUtil.isEmpty(taskList)) {
            return taskList;
        }

        List<String> taskIds = taskList.stream().map(item -> String.valueOf(item.getTaskId())).collect(Collectors.toList());
        List<SysAttach> attachList = sysAttachService.list(new LambdaQueryWrapper<SysAttach>()
                .eq(SysAttach::getModule, AttachModule.TOPIC_TASK.getCode()).in(SysAttach::getRelateId, taskIds));
        List<RwsTaskSample> taskSamples = rwsTaskSampleService.list(new LambdaQueryWrapper<RwsTaskSample>()
                .in(RwsTaskSample::getTaskId, taskIds));
        List<SampleBackup> sampleBackups = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(taskSamples)) {
            List<Long> sampleIds = taskSamples.stream().map(RwsTaskSample::getSampBackupId).collect(Collectors.toList());
            sampleBackups = sampleBackupService.handleResult(sampleBackupService.listByIds(sampleIds));
        }

        List<SampleBackup> finalSampleBackups = sampleBackups;
        List<RwsTask> collect = taskList.stream().map(task -> {
            if (CollectionUtil.isEmpty(task.getAttaches())) {
                task.setAttaches(new ArrayList<>());
            }
            if (CollectionUtil.isEmpty(task.getSampleBackups())) {
                task.setSampleBackups(new ArrayList<>());
            }
            attachList.forEach(attach -> {
                if (String.valueOf(task.getTaskId()).equals(attach.getRelateId())) {
                    task.getAttaches().add(attach);
                }
            });
            taskSamples.forEach(ts -> {
                if (ObjectUtil.equal(ts.getTaskId(), task.getTaskId())) {
                    task.getSampleBackups().add(finalSampleBackups.stream()
                            .filter(s -> ObjectUtil.equal(s.getSampBackupId(), ts.getSampBackupId())).findFirst().orElse(null));
                }
            });
            return task;
        }).collect(Collectors.toList());

        return collect;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveTask(RwsTask rwsTask) {
        rwsTask.setCreateBy(SecurityUtils.getUsername());
        boolean result = this.save(rwsTask);
        // 写入附件表
        List<SysAttach> attaches = rwsTask.getAttaches();
        if (CollectionUtil.isNotEmpty(attaches)) {
            List<SysAttach> attachList = attaches.stream().map(item -> {
                item.setRelateId(String.valueOf(rwsTask.getTaskId()));
                item.setModule(AttachModule.TOPIC_TASK.getCode());
                item.setCreateBy(SecurityUtils.getUsername());
                return item;
            }).collect(Collectors.toList());
            sysAttachService.saveBatch(attachList);
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateTask(RwsTask rwsTask) {
        rwsTask.setUpdateBy(SecurityUtils.getUsername());
        boolean result = this.updateById(rwsTask);
        // 写入附件表
        List<SysAttach> attaches = rwsTask.getAttaches();
        if (CollectionUtil.isNotEmpty(attaches)) {
            List<SysAttach> attachList = attaches.stream().map(item -> {
                item.setRelateId(String.valueOf(rwsTask.getTaskId()));
                item.setModule(AttachModule.TOPIC_TASK.getCode());
                item.setCreateBy(SecurityUtils.getUsername());
                return item;
            }).collect(Collectors.toList());
            sysAttachService.saveOrUpdateBatch(attachList);
        }
        return result;
    }

    @Override
    public boolean removeRelate(RwsTaskSample taskSample) {
        boolean result = rwsTaskSampleService.remove(new LambdaQueryWrapper<RwsTaskSample>()
                .eq(RwsTaskSample::getTaskId, taskSample.getTaskId()).eq(RwsTaskSample::getSampBackupId, taskSample.getSampBackupId()));
        return result;
    }

    @Override
    public boolean addRelate(List<RwsTaskSample> taskSamples) {
        // 存在则不插入 todo 高并发会出问题，后面解决
        if (CollectionUtil.isNotEmpty(taskSamples)) {
            Long taskId = taskSamples.get(0).getTaskId();
            List<RwsTaskSample> taskSampleList = rwsTaskSampleService.list(new LambdaQueryWrapper<RwsTaskSample>().eq(RwsTaskSample::getTaskId, taskId));
            taskSamples.removeAll(taskSampleList);
            return rwsTaskSampleService.saveBatch(taskSamples);
        }
        return false;
    }

    @Override
    public Integer getToTaskCount() {
//        return this.count(new LambdaQueryWrapper<RwsTask>().eq(RwsTask::getTaskState, TopicTaskState.UNDONE.getCode()));
        return this.baseMapper.queryToTaskCount(SecurityUtils.getLoginUser().getUser().getUserId());
    }

    @Override
    public RwsTask getTaskById(Long taskId) {
        List<SysAttach> attachList = sysAttachService.list(new LambdaQueryWrapper<SysAttach>()
                .eq(SysAttach::getModule, AttachModule.TOPIC_TASK.getCode()).eq(SysAttach::getRelateId, String.valueOf(taskId)));
        RwsTask rwsTask = this.getById(taskId);
        rwsTask.setAttaches(attachList);
        return rwsTask;
    }
}
